/**
 * Copyright (C) 2014 Luvina Software Company
 * ValidateUser.java, Dec 15, 2014, Nguyen Huu Luan LA11_AM
 *
 */
package net.luvina.manageuser.validates;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.luvina.manageuser.dao.impl.TblUserDaoImpl;
import net.luvina.manageuser.entities.MstGroup;
import net.luvina.manageuser.entities.MstJapan;
import net.luvina.manageuser.entities.TblUser;
import net.luvina.manageuser.entities.UserInfor;
import net.luvina.manageuser.logics.impl.MstGroupLogicImpl;
import net.luvina.manageuser.logics.impl.MstJapanLogicImpl;
import net.luvina.manageuser.logics.impl.TblUserLogicImpl;
import net.luvina.manageuser.utils.Common;
import net.luvina.manageuser.utils.Constant;
import net.luvina.manageuser.utils.MessageErrorProperties;

/**
 * Validate thông tin user.
 * 
 * @author luan
 * 
 */
public class ValidateUser {

	/**
	 * Validate thông tin user ở màn hình thêm mới/edit user.
	 * 
	 * @param userInfor
	 *            user được validate.
	 * @return danh sách các lỗi trong gói thông tin của user.
	 */
	public static List<String> validateUser(UserInfor userInfor) {
		List<String> lsErrorMess = new ArrayList<String>();
		/*
		 * Check login name.
		 */
		String loginName = userInfor.getLoginName();
		if (loginName != null) {
			if (loginName.length() == 0) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("input_login_name"));
			} else if (!inRangeLength(loginName,
					Constant.MIN_LENGTH_LOGIN_NAME,
					Constant.MAX_LENGTH_LOGIN_NAME)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("login_name_not_in_range"));
			} else if (!isFormatOK(Constant.LOGIN_NAME_PATTERN, loginName)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("login_name_not_match_format"));
			} else if (isLoginNameExist(loginName)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("login_name_exist"));
			}
		}

		/*
		 * Check groupID.
		 */
		int groupId = userInfor.getGroupId();
		if (groupId == 0) {
			lsErrorMess.add(MessageErrorProperties
					.getMessage("choose_group_id"));
		} else if (!isGroupExist(groupId)) {
			lsErrorMess.add(MessageErrorProperties
					.getMessage("group_id_not_exist"));
		}
		/*
		 * Kiểm tra xem full name có hợp lệ hay không.
		 */
		String fullName = userInfor.getFullName();
		if (fullName != null) {
			if (fullName.length() == 0) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("input_full_name"));
			} else if (!checkMaxLength(fullName, Constant.MAX_LENGTH_FULL_NAME)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("full_name_too_long"));
			}
		}
		/*
		 * Kiểm tra xem full name kana có hợp lệ hay không.
		 */
		String fullNameKana = userInfor.getFullNameKana();
		if (fullNameKana != null) {
			if (fullNameKana.length() == 0) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("input_full_name_kana"));
			} else if (!isFormatOK(Constant.KATAKANA_PATTERN, fullNameKana)) {
				lsErrorMess.add(MessageErrorProperties.getMessage("kana_only"));
			} else if (!checkMaxLength(fullNameKana, Constant.MAX_LENGTH_KANA)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("full_name_kana_too_long"));
			}
		}
		/*
		 * Kiểm tra xem ngày sinh có hợp lệ hay không.
		 */
		int[] birthDate = userInfor.getBirthdayADM003();
		if (!isDateExist(birthDate[0], birthDate[1], birthDate[2])) {
			lsErrorMess.add(MessageErrorProperties
					.getMessage("birthday_not_exist"));
		}
		/*
		 * Kiểm tra xem Email có hợp lệ hay không.
		 */
		String email = userInfor.getEmail();
		if (email != null) {
			if (email.length() == 0) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("input_email"));
			} else if (!isFormatOK(Constant.EMAIL_PATTERN, email)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("email_not_match_format"));
			} else if (isEmailExist(email)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("email_exist"));
			} else if (!checkMaxLength(email, Constant.MAX_LENGTH_EMAIL)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("email_too_long"));
			}
		}
		/*
		 * Kiểm tra tel có hợp lệ hay không.
		 */
		String tel = userInfor.getTel();
		if (tel != null) {
			if (tel.length() == 0) {
				lsErrorMess.add(MessageErrorProperties.getMessage("input_tel"));
			} else if (!isTelHalfSize(tel)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("tel_english_number_only"));
			} else if (!isFormatOK(Constant.TEL_PATTERN, tel)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("tel_not_match_format"));
			} else if (!checkMaxLength(tel, Constant.MAX_LENGTH_TEL)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("tel_too_long"));
			}
		}
		/*
		 * Kiểm tra password
		 */
		String password = userInfor.getPassword();
		if (password != null) {
			if (password.length() == 0) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("input_password"));
			} else if (!isOneByte(password)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("password_one_byte_only"));
			} else if (!inRangeLength(password, Constant.MIN_LENGTH_PASSWORD,
					Constant.MAX_LENGTH_PASSWORD)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("password_not_in_range"));
			}
		}
		/*
		 * Kiểm tra passwordConfirm.
		 */
		String passwordConfirm = userInfor.getPasswordConfirm();
		if (password != null) {
			if (!passwordConfirm.equals(password)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("password_not_match"));
			}
		}
		/*
		 * Trình độ tiếng Nhật.
		 */
		String codeLevel = userInfor.getCodeLevel();
		if (!isLevelExist(codeLevel)) {
			lsErrorMess.add(MessageErrorProperties
					.getMessage("level_not_exist"));
		}
		/*
		 * Kiểm tra ngày bắt đầu có giá trị của trình độ tiếng Nhật có hợp lệ
		 * hay không.
		 */
		int[] startDate = userInfor.getStartDateADM003();
		if (!"0".equals(codeLevel)) {
			if (!isDateExist(startDate[0], startDate[1], startDate[2])) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("start_date_not_exist"));
			}
		}
		/*
		 * Kiểm tra ngày hết hạn của trình độ tiếng Nhật có hợp lệ hay không.
		 */
		int[] endDate = userInfor.getEndDateADM003();
		if (!"0".equals(codeLevel)) {
			if (!isDateExist(endDate[0], endDate[1], endDate[2])) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("end_date_not_exist"));
			} else {
				Date tempStartDate = Common.toDate(startDate[0], startDate[1],
						startDate[2]);
				Date tempEndDate = Common.toDate(endDate[0], endDate[1],
						endDate[2]);
				if (tempEndDate.before(tempStartDate)) {
					lsErrorMess.add(MessageErrorProperties
							.getMessage("end_date_gt_start_date"));
				}
			}
		}
		/*
		 * Kiểm tra total có hợp lệ hay không.
		 */
		String totalADM003 = userInfor.getTotalADM003();
		if (!"0".equals(codeLevel)) {
			if ("".equals(totalADM003)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("input_total"));
			} else if (!isHalfSizeNumber(totalADM003)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("total_one_byte_only"));
			}
		}
		return lsErrorMess;
	}

	/**
	 * validateLogin
	 * 
	 * @param loginName
	 *            String loginName
	 * @param password
	 *            String password
	 * @return list errorMess
	 */
	public static List<String> validateLogin(String loginName, String password) {
		List<String> lsErrorMess = new ArrayList<String>();
		if (loginName.trim().length() == 0) {
			lsErrorMess.add(MessageErrorProperties
					.getMessage("input_login_name"));
		}
		if (password.length() == 0) {
			lsErrorMess
					.add(MessageErrorProperties.getMessage("input_password"));
		}
		if (loginName.trim().length() != 0 && password.length() != 0) {
			if (!isUserExist(loginName, password)) {
				lsErrorMess.add(MessageErrorProperties
						.getMessage("input_login_name_password"));
			}
		}

		return lsErrorMess;
	}

	/**
	 * Kiểm tra xem trong DB có user nào với tên loginName và password đã nhập
	 * không.
	 * 
	 * @param loginName
	 *            tên đăng nhập.
	 * @param password
	 *            mật khẩu.
	 * @return true nếu có user trong DB, false nếu không.
	 */
	public static boolean isUserExist(String loginName, String password) {
		TblUserDaoImpl userDao = new TblUserDaoImpl();
		TblUser user = userDao.getUserByLoginNamePassword(loginName, password);
		boolean isExist = false;
		if (user != null) {
			isExist = true;
		}
		return isExist;
	}

	/**
	 * Kiểm tra xem tên đăng nhập đã có trong DB chưa.
	 * 
	 * @param loginName
	 *            tên đăng nhập.
	 * @return true nếu có user trong DB, false nếu không.
	 */
	public static boolean isLoginNameExist(String loginName) {
		boolean isExist = false;
		TblUserLogicImpl userLogic = new TblUserLogicImpl();
		List<String> listLoginName = userLogic.getListLoginName();
		for (String tempLoginName : listLoginName) {
			if (loginName.trim().equals(tempLoginName)) {
				isExist = true;
				break;
			}
		}
		return isExist;
	}

	/**
	 * Kiểm tra xem email đã tồn tại trong cơ sở dữ liệu hay chưa.
	 * 
	 * @param email
	 *            email cần kiểm tra.
	 * @return true nếu đã tồn tại, false nếu chưa tồn tại.
	 */
	public static boolean isEmailExist(String email) {
		boolean isExist = false;
		TblUserLogicImpl userLogic = new TblUserLogicImpl();
		List<String> listEmail = userLogic.getListEmail();
		for (String tempEmail : listEmail) {
			if (email.trim().equals(tempEmail)) {
				isExist = true;
				break;
			}
		}
		return isExist;
	}

	/**
	 * Kiểm tra xem nội dung có đúng với định dạng mong muốn hay không.
	 * 
	 * @param pattern
	 *            định dạng mong muốn.
	 * @param content
	 *            nội dung cần kiểm tra.
	 * @return true nếu khớp với định dạng mong muốn, false nếu không.
	 */
	public static boolean isFormatOK(String pattern, String content) {
		boolean isValid = true;
		Pattern pat = Pattern.compile(pattern);
		Matcher matcher = pat.matcher(content.trim());
		isValid = matcher.matches();
		return isValid;
	}

	/**
	 * Kiểm tra xem chuỗi có chứa toàn kí tự 1 byte hay không.
	 * 
	 * @param content
	 *            chuỗi cần kiểm tra.
	 * @return true nếu chuỗi gồm toàn kí tự 1 byte, false nếu có từ một kí tự 2
	 *         byte trở lên.
	 */
	public static boolean isOneByte(String content) {
		boolean isValid = true;
		for (int i = 0; i < content.length(); i++) {
			char c = content.charAt(i);
			if ((int) c > 255) {
				isValid = false;
				break;
			}
		}
		return isValid;
	}

	/**
	 * Kiểm tra xem một chuỗi có bao gồm toàn kí tự số half size hay không.
	 * 
	 * @param content
	 *            chuỗi kí tự cần kiểm tra.
	 * @return true nếu bao gồm toàn chuỗi 1 byte, false nếu có từ 1 kí tự trở
	 *         lên không phải là số halfsize.
	 */
	public static boolean isHalfSizeNumber(String content) {
		boolean isValid = true;
		for (int i = 0; i < content.length(); i++) {
			char c = content.charAt(i);
			if ((int) c < 48 || (int) c > 57) {
				isValid = false;
				break;
			}
		}
		return isValid;
	}

	/**
	 * Kiểm tra xem ngày tháng có tồn tại hay không.
	 * 
	 * @param year
	 *            năm.
	 * @param month
	 *            tháng.
	 * @param day
	 *            ngày.
	 * @return true nếu tồn tại, false nếu không tồn tại.
	 */
	public static boolean isDateExist(int year, int month, int day) {
		boolean isValid = false;
		String dateFormat = Constant.DATE_FORMAT;
		String dateStr = year + "/" + month + "/" + day;
		SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
		sdf.setLenient(false);
		try {
			sdf.parse(dateStr);
			isValid = true;
		} catch (ParseException e) {
			System.out.println("Date is not valid!");
		}
		return isValid;
	}

	/**
	 * Kiểm tra xem độ dài của chuỗi có nằm trong khoảng max min cho phép hay
	 * không, sau khi loại bỏ khoảng trắng ở hai đầu.
	 * 
	 * @param content
	 *            nội dung cần kiểm tra.
	 * @param min
	 *            chiều dài tối thiểu của chuỗi.
	 * @param max
	 *            chiều dài tối đa của chuỗi.
	 * @return true nếu nằm trong giới hạn, false nếu không nằm trong giới hạn.
	 */
	public static boolean inRangeLength(String content, int min, int max) {
		boolean isValid = true;
		int length = content.trim().length();
		if (length < min || length > max) {
			isValid = false;
		}
		return isValid;
	}

	/**
	 * Kiểm tra xem chuỗi đưa vào có độ dài vượt quá giới hạn max hay không.
	 * 
	 * @param content
	 *            chuỗi cần kiểm tra.
	 * @param max
	 *            giới hạn chiều dài của chuỗi.
	 * @return true nếu không vượt quá giới hạn chiều dài, false nếu vượt quá
	 *         giới hạn chiều dài.
	 */
	public static boolean checkMaxLength(String content, int max) {
		boolean isValid = true;
		if (content.length() > max) {
			isValid = false;
		}
		return isValid;
	}

	/**
	 * Kiểm tra xem nhóm có tồn tại hay không.
	 * 
	 * @param groupId
	 *            nhóm cần kiểm tra.
	 * @return true nếu tồn tại, false nếu không.
	 */
	public static boolean isGroupExist(int groupId) {
		boolean isExist = false;
		MstGroupLogicImpl groupLogic = new MstGroupLogicImpl();
		List<MstGroup> listGroup = groupLogic.getAllMstGroups();
		for (MstGroup group : listGroup) {
			if (groupId == group.getGroupId()) {
				isExist = true;
				break;
			}
		}
		return isExist;
	}

	/**
	 * Kiểm tra xem level có tồn tại hay không.
	 * 
	 * @param codeLevel
	 *            level cần kiểm tra.
	 * @return true nếu tồn tại, false nếu không.
	 */
	public static boolean isLevelExist(String codeLevel) {
		boolean isExist = false;
		if ("0".equals(codeLevel)) {
			isExist = true;
		} else {
			MstJapanLogicImpl japanLogic = new MstJapanLogicImpl();
			List<MstJapan> listJapan = japanLogic.getAllMstJapan();
			for (MstJapan japan : listJapan) {
				if (codeLevel.equals(japan.getCodeLevel())) {
					isExist = true;
					break;
				}
			}
		}
		return isExist;
	}

	/**
	 * Kiểm tra xem các chữ số trong số điện thoại có phải là số half size hay
	 * không.
	 * 
	 * @param tel
	 *            chuỗi số điện thoại cần hiểm tra, có định dạng:
	 *            xxxx-xxxx-xxxx, trong đó, x là một chữ số.
	 * @return true nếu các chữ số là số halfsize, false nếu có từ một chữ số
	 *         trở lên không phải là số halfsize.
	 */
	public static boolean isTelHalfSize(String tel) {
		boolean isValid = true;
		StringTokenizer token = new StringTokenizer(tel, "-");
		if (token.hasMoreElements()) {
			isHalfSizeNumber(token.nextToken());
		}
		return isValid;
	}
}
